<?php if (!defined('THINK_PATH')) exit();?><!DOCTYPE html>
<html lang="zh-CN">
	
<head>
	<title>重点知识 — Vue.js</title>
	<meta charset="utf-8">
	<meta name="description" content="Vue.js - The Progressive JavaScript Framework">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

	<script src="/js/jquery-3.1.0.min.js" type="text/javascript"></script>
	<script type="text/javascript" src="/js/prettify.js"></script>
	<script type="text/javascript" src="/js/content.js"></script>
	<link rel="stylesheet" href="/css/prettify.css">
	<link rel="icon" href="/images/logo.png" type="image/png">


	<link rel="stylesheet" type="text/css" href="/css/vuex.css"/>
	<script type="text/javascript" src="/js/vue.js"></script>



	<!-- main page styles -->
	<link rel="stylesheet" href="/css/page.css">
<style type="text/css">
	.content .linenums>ol {
		margin: 0;
		padding-left:35px;
	}
	.hljs-comment,.hljs-quote{color:#8e908c}
	.hljs-deletion,.hljs-name,.hljs-regexp,.hljs-selector-class,.hljs-selector-id,.hljs-tag,.hljs-template-variable,.hljs-variable{color:#c82829}
	.hljs-built_in,.hljs-builtin-name,.hljs-link,.hljs-literal,.hljs-meta,.hljs-number,.hljs-params,.hljs-type{color:#f5871f}
	.hljs-attribute{color:#eab700}
	.hljs-addition,.hljs-bullet,.hljs-string,.hljs-symbol{color:#718c00}
	.hljs-section,.hljs-title{color:#4271ae}
	.hljs-keyword,.hljs-selector-tag{color:#8959a8}
	.hljs{display:block;overflow-x:auto;background:#fff;color:#4d4d4c;padding:.5em}
	.hljs-emphasis{font-style:italic}
	.hljs-strong{font-weight:700}
</style>
</head>

<body class="docs">


<div id="header">
	<a id="logo" href="https://cn.vuejs.org/">
		<img src="/images/logo.png">
		<span>Vuecli</span>
	</a>
</div>


<div id="main" class="fix-sidebar">
	<div class="sidebar">
		<div class="sidebar-inner">
			<div class="list">
			<ul class="menu-root">
	<li>
		<h3>知识点</h3>
	</li>
	<li id="stylus" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/stylus" class="sidebar-link">stylus</a>
		<ul class="menu-sub">
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/stylus#变量">变量</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/stylus#@import引入">@import引入</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/stylus#特殊用法">特殊用法</a>
			</li>
<!--
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/index#Vue-js-是什么">Vue.js 是什么</a>
			</li>
			<ul>
				<li>
					<a class="section-link" data-scroll="" href="/Vuecli/index#与自定义元素的关系">与自定义元素的关系</a>
				</li>
			</ul>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/index#准备好了吗？">准备好了吗？</a>
			</li> -->
		</ul>
	</li>

	<li id="axios" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/axios" class="sidebar-link">axios</a>
		<ul class="menu-sub">
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#Features">Features</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#浏览器支持">浏览器支持</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#安装">安装</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#Example">Example</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#API">axios API</a>
			</li>
			<ul>
				<li>
					<a class="section-link" data-scroll="" href="/Vuecli/axios#请求方法的别名">请求方法的别名</a>
				</li>
				<li>
					<a class="section-link" data-scroll="" href="/Vuecli/axios#并发">并发</a>
				</li>
				<li>
					<a class="section-link" data-scroll="" href="/Vuecli/axios#创建实例">创建实例</a>
				</li>
				<li>
					<a class="section-link" data-scroll="" href="/Vuecli/axios#实例方法">实例方法</a>
				</li>
			</ul>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#请求配置">请求配置</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#响应结构">响应结构</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#defaults">配置的默认值/defaults</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#拦截器">拦截器</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#错误处理">错误处理</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#取消">取消</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/axios#Semver">Semver</a>
			</li>
		</ul>
	</li>


	<li>
		<h3>Vue Router</h3>
	</li>
	<li id="vrouter-start" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/vrouter-start" class="sidebar-link">安装 与 介绍</a>
		<ul class="menu-sub">
			<li><a href="/Vuecli/vrouter-start#installation" data-scroll="" class="section-link">安装</a></li>
			<li><a href="/Vuecli/vrouter-start#introduce" data-scroll="" class="section-link">介绍</a></li>
		</ul>
	</li>
	<li id="vrouter-basic" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/vrouter-basic" class="sidebar-link">基础</a>
		<ul class="menu-sub">
			<li><a href="/Vuecli/vrouter-basic#start" class="sidebar-link">起步</a></li>
			<ul>
				<li><a href="/Vuecli/vrouter-basic#start-html" class="sidebar-link">HTML</a></li>
				<li><a href="/Vuecli/vrouter-basic#start-javascript" class="sidebar-link">JavaScript</a></li>
			</ul>

			<li><a href="/Vuecli/vrouter-basic#dynamic_matching" class="sidebar-link">动态路由匹配</a></li>
			<ul>
				<li><a href="/Vuecli/vrouter-basic#dynamic_matching-响应路由参数的变化" class="sidebar-link">响应路由参数的变化</a></li>
				<li><a href="/Vuecli/vrouter-basic#dynamic_matching-高级匹配模式" class="sidebar-link">高级匹配模式</a></li>
				<li><a href="/Vuecli/vrouter-basic#dynamic_matching-匹配优先级" class="sidebar-link">匹配优先级</a></li>
			</ul>

			<li><a href="/Vuecli/vrouter-basic#nested-routes" class="sidebar-link">嵌套路由</a></li>
			
			<li><a href="/Vuecli/vrouter-basic#navigation" class="sidebar-link">编程式的导航</a></li>
			
			<li><a href="/Vuecli/vrouter-basic#named-routes" class="sidebar-link">命名路由</a></li>
			
			<li><a href="/Vuecli/vrouter-basic#named_views" class="sidebar-link">命名视图</a></li>
			<ul>
				<li><a href="/Vuecli/vrouter-basic#named_views-嵌套命名视图" class="sidebar-link">嵌套命名视图</a></li>
			</ul>

			<li><a href="/Vuecli/vrouter-basic#redirect_and_alias" class="sidebar-link">重定向和别名</a></li>
			<ul>
				<li><a href="/Vuecli/vrouter-basic#redirect_and_alias-重定向" class="sidebar-link">重定向</a></li>
				<li><a href="/Vuecli/vrouter-basic#redirect_and_alias-别名" class="sidebar-link">别名</a></li>
			</ul>

			<li><a href="/Vuecli/vrouter-basic#passing_props" class="sidebar-link">路由组件传参</a></li>
			<ul>
				<li><a href="/Vuecli/vrouter-basic#passing_props-布尔模式" class="sidebar-link">布尔模式</a></li>
				<li><a href="/Vuecli/vrouter-basic#passing_props-对象模式" class="sidebar-link">对象模式</a></li>
				<li><a href="/Vuecli/vrouter-basic#passing_props-函数模式" class="sidebar-link">函数模式</a></li>
			</ul>

			<li><a href="/Vuecli/vrouter-basic#history_mode" class="sidebar-link">HTML5 History 模式</a></li>
			<ul>
				<li><a href="/Vuecli/vrouter-basic#history_mode-后端配置例子" class="sidebar-link">后端配置例子</a></li>
				<li><a href="/Vuecli/vrouter-basic#history_mode-警告" class="sidebar-link">警告</a></li>
			</ul>
		</ul>
	</li>
	<li id="vrouter-advanced" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/vrouter-advanced" class="sidebar-link">进阶</a>
		<ul class="menu-sub">
			<li><a href="/Vuecli/advanced#navigation_guards" class="active sidebar-link">导航守卫</a></li>
			<ul>
				<li><a href="/Vuecli/advanced#navigation_guards-全局守卫" class="sidebar-link">全局守卫</a></li>
				<li><a href="/Vuecli/advanced#navigation_guards-全局解析守卫" class="sidebar-link">全局解析守卫</a></li>
				<li><a href="/Vuecli/advanced#navigation_guards-全局后置钩子" class="sidebar-link">全局后置钩子</a></li>
				<li><a href="/Vuecli/advanced#navigation_guards-路由独享的守卫" class="sidebar-link">路由独享的守卫</a></li>
				<li><a href="/Vuecli/advanced#navigation_guards-组件内的守卫" class="sidebar-link">组件内的守卫</a></li>
				<li><a href="/Vuecli/advanced#navigation_guards-完整的导航解析流程" class="sidebar-link">完整的导航解析流程</a></li>
			</ul>
		
			<li><a href="/Vuecli/advanced#meta" class="sidebar-link">路由元信息</a></li>
		
			<li><a href="/Vuecli/advanced#transitions" class="sidebar-link">过渡动效</a></li>
			<ul>
				<li><a href="/Vuecli/advanced#transitions-单个路由的过渡" class="sidebar-link">单个路由的过渡</a></li>
				<li><a href="/Vuecli/advanced#transitions-基于路由的动态过渡" class="sidebar-link">基于路由的动态过渡</a></li>
			</ul>
		
			<li><a href="/Vuecli/advanced#data_fetching" class="sidebar-link">数据获取</a></li>
			<ul>
				<li><a href="/Vuecli/advanced#data_fetching-导航完成后获取数据" class="sidebar-link">导航完成后获取数据</a></li>
				<li><a href="/Vuecli/advanced#data_fetching-在导航完成前获取数据" class="sidebar-link">在导航完成前获取数据</a></li>
			</ul>
		
			<li><a href="/Vuecli/advanced#scroll_behavior" class="sidebar-link">滚动行为</a></li>
			<ul>
				<li><a href="/Vuecli/advanced#scroll_behavior-异步滚动" class="sidebar-link">异步滚动</a></li>
			</ul>
		
			<li><a href="/Vuecli/advanced#lazy_loading" class="sidebar-link">路由懒加载</a></li>
			<ul>
				<li><a href="/Vuecli/advanced#lazy_loading-把组件按组分块" class="sidebar-link">把组件按组分块</a></li>
			</ul>
		</ul>
	</li>


	<li>
		<h3>Vuex</h3>
	</li>
	<li id="vuex-start" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/vuex-start" class="sidebar-link">安装 与 介绍</a>
		<ul class="menu-sub">
			<li><a href="/Vuecli/vuex-start#installation" data-scroll="" class="section-link">安装</a></li>
			<li><a href="/Vuecli/vuex-start#introduce" data-scroll="" class="section-link">Vuex 是什么？</a></li>
			<li><a href="/Vuecli/vuex-start#vrouter-basic0" data-scroll="" class="section-link">开始</a></li>
		</ul>
	</li>
	<li id="vuex-guide" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/vuex-guide" class="sidebar-link">核心概念</a>
		<ul class="menu-sub">
			<li><a href="/Vuecli/vuex-guide#state" data-scroll="" class="section-link">State</a></li>
			<li><a href="/Vuecli/vuex-guide#getters" data-scroll="" class="section-link">Getter</a></li>
			<li><a href="/Vuecli/vuex-guide#mutations" data-scroll="" class="section-link">Mutation</a></li>
			<li><a href="/Vuecli/vuex-guide#actions" data-scroll="" class="section-link">Action</a></li>
			<li><a href="/Vuecli/vuex-guide#modules" data-scroll="" class="section-link">Module</a></li>
		</ul>
	</li>
	<li id="vuex-important" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/vuex-important" class="sidebar-link">重点知识</a>
		<ul class="menu-sub">
			<li><a href="/Vuecli/vuex-important#structure" data-scroll="" class="section-link">项目结构</a></li>
			<li><a href="/Vuecli/vuex-important#plugins" data-scroll="" class="section-link">插件</a></li>
			<li><a href="/Vuecli/vuex-important#strict" data-scroll="" class="section-link">严格模式</a></li>
			<li><a href="/Vuecli/vuex-important#forms" data-scroll="" class="section-link">表单处理</a></li>
			<li><a href="/Vuecli/vuex-important#testing" data-scroll="" class="section-link">测试</a></li>
			<li><a href="/Vuecli/vuex-important#hot-reload" data-scroll="" class="section-link">热重载</a></li>
		</ul>
	</li>





	<li>
		<h3>框架布局</h3>
	</li>
	<li id="mulujiegou" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/mulujiegou" class="sidebar-link">目录结构</a>
		<ul class="menu-sub">
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/mulujiegou#总体框架">总体框架</a>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/mulujiegou#文件结构细分">文件结构细分</a>
				<ul>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/mulujiegou#build">build - [webpack配置]</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/mulujiegou#config">config - [vue项目配置]</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/mulujiegou#node_modules">node_modules - [依赖包]</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/mulujiegou#router">router - [路由配置]</a>
					</li>
				</ul>
			</li>
		</ul>
	</li>


	<li id="huanjingpeizhi" class="sidebar-menu">
		<i class="">＋</i>
		<a href="/Vuecli/huanjingpeizhi" class="sidebar-link">基于webpack 环境配置</a>
		<ul class="menu-sub">
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#安装">安装</a>
				<ul>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#node">安装node.js LTS版本 cmd</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#vuecli">安装vue-cil 全局安装一次 cmd</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#webpack">创建 webpack模板的项目 cmd</a>
					</li>
				</ul>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#运行服务器">运行服务器</a>
				<ul>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#运行服务器0">运行服务器 cmd</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#cmd其他操作命令">cmd其他操作命令</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#stylus">安装 stylus</a>
					</li>
				</ul>
			</li>
			<li>
				<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#代码初始化">代码初始化</a>
				<ul>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#viewport">viewport index.html</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#resetcss">reset.css 样式初始化</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#bordercss">border.css 1像素边框</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#fastclick">fastclick.js 解决点击延时</a>
					</li>
					<li>
						<a class="section-link" data-scroll="" href="/Vuecli/huanjingpeizhi#iconfont">iconfont</a>
					</li>
				</ul>
			</li>
		</ul>
	</li>

</ul>

			</div>
		</div>
	</div>

	
<div class="content guide with-sidebar components-guide">
<h1>重点知识</h1>	

<h2 id="structure">
	<a href="#structure" class="headerlink" title="structure" data-scroll="">项目结构</a>
</h2>
<p>Vuex 并不限制你的代码结构。但是，它规定了一些需要遵守的规则：</p>
<ol>
	<li>
		<p>应用层级的状态应该集中到单个 store 对象中。</p>
	</li>
	<li>
		<p>提交 <strong>mutation</strong> 是更改状态的唯一方法，并且这个过程是同步的。</p>
	</li>
	<li>
		<p>异步逻辑都应该封装到 <strong>action</strong> 里面。</p>
	</li>
</ol>
<p>只要你遵守以上规则，如何组织代码随你便。如果你的 store 文件太大，只需将 action、mutation 和 getter 分割到单独的文件。</p>
<p>对于大型应用，我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例：</p>
<div class="language-bash extra-class">
	<pre class="language-bash"><code>├── index.html
├── main.js
├── api
│   └── <span class="token punctuation">..</span>. <span class="token comment"># 抽取出API请求</span>
├── components
│   ├── App.vue
│   └── <span class="token punctuation">..</span>.
└── store
    ├── index.js          <span class="token comment"># 我们组装模块并导出 store 的地方</span>
    ├── actions.js        <span class="token comment"># 根级别的 action</span>
    ├── mutations.js      <span class="token comment"># 根级别的 mutation</span>
    └── modules
        ├── cart.js       <span class="token comment"># 购物车模块</span>
        └── products.js   <span class="token comment"># 产品模块</span>
</code></pre>
</div>
<p>请参考<a href="https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart" target="_blank" rel="noopener noreferrer">购物车示例<svg
		 xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"
		 class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a>。</p>

<br><br>

	
<h2 id="plugins">
	<a href="#plugins" class="headerlink" title="plugins" data-scroll="">插件</a>
</h2>	
<p>Vuex 的 store 接受 <code>plugins</code> 选项，这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数，它接收 store 作为唯一参数：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">myPlugin</span> <span class="token operator">=</span> store <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 当 store 初始化后调用</span>
  store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">(</span>mutation<span class="token punctuation">,</span> state<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 每次 mutation 之后调用</span>
    <span class="token comment">// mutation 的格式为 { type, payload }</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<p>然后像这样使用：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
  plugins<span class="token punctuation">:</span> <span class="token punctuation">[</span>myPlugin<span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<h3 id="在插件内提交-mutation"><a href="#在插件内提交-mutation" aria-hidden="true" class="header-anchor">在插件内提交 Mutation</a></h3>
<p>在插件中不允许直接修改状态——类似于组件，只能通过提交 mutation 来触发变化。</p>
<p>通过提交 mutation，插件可以用来同步数据源到 store。例如，同步 websocket 数据源到 store（下面是个大概例子，实际上 <code>createPlugin</code>
	方法可以有更多选项来完成复杂任务）：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">createWebSocketPlugin</span> <span class="token punctuation">(</span>socket<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> store <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    socket<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'data'</span><span class="token punctuation">,</span> data <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      store<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'receiveData'</span><span class="token punctuation">,</span> data<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>mutation <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>mutation<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token string">'UPDATE_DATA'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        socket<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'update'</span><span class="token punctuation">,</span> mutation<span class="token punctuation">.</span>payload<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> plugin <span class="token operator">=</span> <span class="token function">createWebSocketPlugin</span><span class="token punctuation">(</span>socket<span class="token punctuation">)</span>

<span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  state<span class="token punctuation">,</span>
  mutations<span class="token punctuation">,</span>
  plugins<span class="token punctuation">:</span> <span class="token punctuation">[</span>plugin<span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<h3 id="生成-state-快照"><a href="#生成-state-快照" aria-hidden="true" class="header-anchor">生成 State 快照</a></h3>
<p>有时候插件需要获得状态的“快照”，比较改变的前后状态。想要实现这项功能，你需要对状态对象进行深拷贝：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">myPluginWithSnapshot</span> <span class="token operator">=</span> store <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> prevState <span class="token operator">=</span> _<span class="token punctuation">.</span><span class="token function">cloneDeep</span><span class="token punctuation">(</span>store<span class="token punctuation">.</span>state<span class="token punctuation">)</span>
  store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">(</span>mutation<span class="token punctuation">,</span> state<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> nextState <span class="token operator">=</span> _<span class="token punctuation">.</span><span class="token function">cloneDeep</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span>

    <span class="token comment">// 比较 prevState 和 nextState...</span>

    <span class="token comment">// 保存状态，用于下一次 mutation</span>
    prevState <span class="token operator">=</span> nextState
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<p><strong>生成状态快照的插件应该只在开发阶段使用</strong>，使用 webpack 或 Browserify，让构建工具帮我们处理：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
  plugins<span class="token punctuation">:</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">!==</span> <span class="token string">'production'</span>
    <span class="token operator">?</span> <span class="token punctuation">[</span>myPluginWithSnapshot<span class="token punctuation">]</span>
    <span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<p>上面插件会默认启用。在发布阶段，你需要使用 webpack 的 <a href="https://webpack.js.org/plugins/define-plugin/" target="_blank" rel="noopener noreferrer">DefinePlugin<svg
		 xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"
		 class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a> 或者是 Browserify 的 <a href="https://github.com/hughsk/envify" target="_blank" rel="noopener noreferrer">envify<svg
		 xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"
		 class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a> 使 <code>process.env.NODE_ENV !== 'production'</code> 为 <code>false</code>。</p>
<h3 id="内置-logger-插件"><a href="#内置-logger-插件" aria-hidden="true" class="header-anchor">内置 Logger 插件</a></h3>
<blockquote>
	<p>如果正在使用 <a href="https://github.com/vuejs/vue-devtools" target="_blank" rel="noopener noreferrer">vue-devtools<svg
			 xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"
			 class="icon outbound">
				<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
				<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
			</svg></a>，你可能不需要此插件。</p>
</blockquote>
<p>Vuex 自带一个日志插件用于一般的调试:</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">import</span> createLogger <span class="token keyword">from</span> <span class="token string">'vuex/dist/logger'</span>

<span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  plugins<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token function">createLogger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<p><code>createLogger</code> 函数有几个配置项：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> logger <span class="token operator">=</span> <span class="token function">createLogger</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  collapsed<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 自动展开记录的 mutation</span>
  <span class="token function">filter</span> <span class="token punctuation">(</span>mutation<span class="token punctuation">,</span> stateBefore<span class="token punctuation">,</span> stateAfter<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 若 mutation 需要被记录，就让它返回 true 即可</span>
    <span class="token comment">// 顺便，`mutation` 是个 { type, payload } 对象</span>
    <span class="token keyword">return</span> mutation<span class="token punctuation">.</span>type <span class="token operator">!==</span> <span class="token string">"aBlacklistedMutation"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">transformer</span> <span class="token punctuation">(</span>state<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 在开始记录之前转换状态</span>
    <span class="token comment">// 例如，只返回指定的子树</span>
    <span class="token keyword">return</span> state<span class="token punctuation">.</span>subTree
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">mutationTransformer</span> <span class="token punctuation">(</span>mutation<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// mutation 按照 { type, payload } 格式记录</span>
    <span class="token comment">// 我们可以按任意方式格式化</span>
    <span class="token keyword">return</span> mutation<span class="token punctuation">.</span>type
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  logger<span class="token punctuation">:</span> console<span class="token punctuation">,</span> <span class="token comment">// 自定义 console 实现，默认为 `console`</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<p>日志插件还可以直接通过 <code>&lt;script&gt;</code> 标签引入，它会提供全局方法 <code>createVuexLogger</code>。</p>
<p>要注意，logger 插件会生成状态快照，所以仅在开发环境使用。</p>


<br><br>


	
<h2 id="strict">
	<a href="#strict" class="headerlink" title="strict" data-scroll="">严格模式</a>
</h2>	
	
<p>开启严格模式，仅需在创建 store 的时候传入 <code>strict: true</code>：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
  strict<span class="token punctuation">:</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<p>在严格模式下，无论何时发生了状态变更且不是由 mutation 函数引起的，将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。</p>
<h3 id="开发环境与发布环境"><a href="#开发环境与发布环境" aria-hidden="true" class="header-anchor">开发环境与发布环境</a></h3>
<p>**不要在发布环境下启用严格模式！**严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式，以避免性能损失。</p>
<p>类似于插件，我们可以让构建工具来处理这种情况：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
  strict<span class="token punctuation">:</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">!==</span> <span class="token string">'production'</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
	
<br><br>
	
	
<h2 id="forms">
	<a href="#forms" class="headerlink" title="forms" data-scroll="">表单处理</a>
</h2>	

<p>当在严格模式中使用 Vuex 时，在属于 Vuex 的 state 上使用 <code>v-model</code> 会比较棘手：</p>
<div class="language-html extra-class">
	<pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">v-model</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>obj.message<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
</code></pre>
</div>
<p>假设这里的 <code>obj</code> 是在计算属性中返回的一个属于 Vuex store 的对象，在用户输入时，<code>v-model</code> 会试图直接修改 <code>obj.message</code>。在严格模式中，由于这个修改不是在
	mutation 函数中执行的, 这里会抛出一个错误。</p>
<p>用“Vuex 的思维”去解决这个问题的方法是：给 <code>&lt;input&gt;</code> 中绑定 value，然后侦听 <code>input</code> 或者 <code>change</code>
	事件，在事件回调中调用 action:</p>
<div class="language-html extra-class">
	<pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">:value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>message<span class="token punctuation">"</span></span> <span class="token attr-name">@input</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>updateMessage<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
</code></pre>
</div>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// ...</span>
computed<span class="token punctuation">:</span> <span class="token punctuation">{</span>
  <span class="token operator">...</span><span class="token function">mapState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    message<span class="token punctuation">:</span> state <span class="token operator">=&gt;</span> state<span class="token punctuation">.</span>obj<span class="token punctuation">.</span>message
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
methods<span class="token punctuation">:</span> <span class="token punctuation">{</span>
  <span class="token function">updateMessage</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'updateMessage'</span><span class="token punctuation">,</span> e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<p>下面是 mutation 函数：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// ...</span>
mutations<span class="token punctuation">:</span> <span class="token punctuation">{</span>
  <span class="token function">updateMessage</span> <span class="token punctuation">(</span>state<span class="token punctuation">,</span> message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    state<span class="token punctuation">.</span>obj<span class="token punctuation">.</span>message <span class="token operator">=</span> message
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<h3 id="双向绑定的计算属性"><a href="#双向绑定的计算属性" aria-hidden="true" class="header-anchor">双向绑定的计算属性</a> </h3>
<p>必须承认，这样做比简单地使用“<code>v-model</code> + 局部状态”要啰嗦得多，并且也损失了一些 <code>v-model</code> 中很有用的特性。另一个方法是使用带有 setter 的双向绑定计算属性：</p>
<div class="language-html extra-class">
	<pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">v-model</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>message<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
</code></pre>
</div>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// ...</span>
computed<span class="token punctuation">:</span> <span class="token punctuation">{</span>
  message<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    <span class="token keyword">get</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span>state<span class="token punctuation">.</span>obj<span class="token punctuation">.</span>message
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token keyword">set</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'updateMessage'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</div>


<br><br>
	
<h2 id="testing">
	<a href="#testing" class="headerlink" title="testing" data-scroll="">测试</a>
</h2>	
<p>我们主要想针对 Vuex 中的 mutation 和 action 进行单元测试。</p>
<h3 id="测试-mutation"><a href="#测试-mutation" aria-hidden="true" class="header-anchor">测试 Mutation</a></h3>
<p>Mutation 很容易被测试，因为它们仅仅是一些完全依赖参数的函数。这里有一个小技巧，如果你在 <code>store.js</code> 文件中定义了 mutation，并且使用 ES2015 模块功能默认输出了
	Vuex.Store 的实例，那么你仍然可以给 mutation 取个变量名然后把它输出去：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>

<span class="token comment">// `mutations` 作为命名输出对象</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> mutations <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  state<span class="token punctuation">,</span>
  mutations
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<p>下面是用 Mocha + Chai 测试一个 mutation 的例子（实际上你可以用任何你喜欢的测试框架）：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// mutations.js</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> mutations <span class="token operator">=</span> <span class="token punctuation">{</span>
  increment<span class="token punctuation">:</span> state <span class="token operator">=&gt;</span> state<span class="token punctuation">.</span>count<span class="token operator">++</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// mutations.spec.js</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> expect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'chai'</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> mutations <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./store'</span>

<span class="token comment">// 解构 `mutations`</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> increment <span class="token punctuation">}</span> <span class="token operator">=</span> mutations

<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'mutations'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'INCREMENT'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 模拟状态</span>
    <span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> count<span class="token punctuation">:</span> <span class="token number">0</span> <span class="token punctuation">}</span>
    <span class="token comment">// 应用 mutation</span>
    <span class="token function">increment</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span>
    <span class="token comment">// 断言结果</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>state<span class="token punctuation">.</span>count<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span><span class="token function">equal</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<h3 id="测试-action"><a href="#测试-action" aria-hidden="true" class="header-anchor">测试 Action</a></h3>
<p>Action 应对起来略微棘手，因为它们可能需要调用外部的 API。当测试 action 的时候，我们需要增加一个 mocking 服务层——例如，我们可以把 API 调用抽象成服务，然后在测试文件中用 mock 服务回应 API
	调用。为了便于解决 mock 依赖，可以用 webpack 和 <a href="https://github.com/plasticine/inject-loader" target="_blank" rel="noopener noreferrer">inject-loader<svg
		 xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"
		 class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a> 打包测试文件。</p>
<p>下面是一个测试异步 action 的例子：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// actions.js</span>
<span class="token keyword">import</span> shop <span class="token keyword">from</span> <span class="token string">'../api/shop'</span>

<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">getAllProducts</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> commit <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'REQUEST_PRODUCTS'</span><span class="token punctuation">)</span>
  shop<span class="token punctuation">.</span><span class="token function">getProducts</span><span class="token punctuation">(</span>products <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'RECEIVE_PRODUCTS'</span><span class="token punctuation">,</span> products<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// actions.spec.js</span>

<span class="token comment">// 使用 require 语法处理内联 loaders。</span>
<span class="token comment">// inject-loader 返回一个允许我们注入 mock 依赖的模块工厂</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> expect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'chai'</span>
<span class="token keyword">const</span> actionsInjector <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'inject-loader!./actions'</span><span class="token punctuation">)</span>

<span class="token comment">// 使用 mocks 创建模块</span>
<span class="token keyword">const</span> actions <span class="token operator">=</span> <span class="token function">actionsInjector</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token string">'../api/shop'</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
    <span class="token function">getProducts</span> <span class="token punctuation">(</span>cb<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token function">cb</span><span class="token punctuation">(</span><span class="token punctuation">[</span> <span class="token comment">/* mocked response */</span> <span class="token punctuation">]</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 用指定的 mutations 测试 action 的辅助函数</span>
<span class="token keyword">const</span> <span class="token function-variable function">testAction</span> <span class="token operator">=</span> <span class="token punctuation">(</span>action<span class="token punctuation">,</span> args<span class="token punctuation">,</span> state<span class="token punctuation">,</span> expectedMutations<span class="token punctuation">,</span> done<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> count <span class="token operator">=</span> <span class="token number">0</span>

  <span class="token comment">// 模拟提交</span>
  <span class="token keyword">const</span> <span class="token function-variable function">commit</span> <span class="token operator">=</span> <span class="token punctuation">(</span>type<span class="token punctuation">,</span> payload<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> mutation <span class="token operator">=</span> expectedMutations<span class="token punctuation">[</span>count<span class="token punctuation">]</span>

    <span class="token keyword">try</span> <span class="token punctuation">{</span>
      <span class="token function">expect</span><span class="token punctuation">(</span>mutation<span class="token punctuation">.</span>type<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span><span class="token function">equal</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>payload<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">expect</span><span class="token punctuation">(</span>mutation<span class="token punctuation">.</span>payload<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span>deep<span class="token punctuation">.</span><span class="token function">equal</span><span class="token punctuation">(</span>payload<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">done</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    count<span class="token operator">++</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>count <span class="token operator">&gt;=</span> expectedMutations<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">done</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 用模拟的 store 和参数调用 action</span>
  <span class="token function">action</span><span class="token punctuation">(</span><span class="token punctuation">{</span> commit<span class="token punctuation">,</span> state <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token operator">...</span>args<span class="token punctuation">)</span>

  <span class="token comment">// 检查是否没有 mutation 被 dispatch</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>expectedMutations<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>count<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span><span class="token function">equal</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
    <span class="token function">done</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'actions'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'getAllProducts'</span><span class="token punctuation">,</span> done <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">testAction</span><span class="token punctuation">(</span>actions<span class="token punctuation">.</span>getAllProducts<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'REQUEST_PRODUCTS'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'RECEIVE_PRODUCTS'</span><span class="token punctuation">,</span> payload<span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token comment">/* mocked response */</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span> done<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<p>如果在测试环境下有可用的 spy (比如通过 <a href="http://sinonjs.org/" target="_blank" rel="noopener noreferrer">Sinon.JS<svg xmlns="http://www.w3.org/2000/svg"
		 aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a>)，你可以使用它们替换辅助函数 <code>testAction</code>：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'actions'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'getAllProducts'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> commit <span class="token operator">=</span> sinon<span class="token punctuation">.</span><span class="token function">spy</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
    
    actions<span class="token punctuation">.</span><span class="token function">getAllProducts</span><span class="token punctuation">(</span><span class="token punctuation">{</span> commit<span class="token punctuation">,</span> state <span class="token punctuation">}</span><span class="token punctuation">)</span>
    
    <span class="token function">expect</span><span class="token punctuation">(</span>commit<span class="token punctuation">.</span>args<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span>deep<span class="token punctuation">.</span><span class="token function">equal</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
      <span class="token punctuation">[</span><span class="token string">'REQUEST_PRODUCTS'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">[</span><span class="token string">'RECEIVE_PRODUCTS'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token comment">/* mocked response */</span> <span class="token punctuation">}</span><span class="token punctuation">]</span>
    <span class="token punctuation">]</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<h3 id="测试-getter"><a href="#测试-getter" aria-hidden="true" class="header-anchor">测试 Getter</a></h3>
<p>如果你的 getter 包含很复杂的计算过程，很有必要测试它们。Getter 的测试与 mutation 一样直截了当。</p>
<p>测试一个 getter 的示例：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// getters.js</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> getters <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token function">filteredProducts</span> <span class="token punctuation">(</span>state<span class="token punctuation">,</span> <span class="token punctuation">{</span> filterCategory <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> state<span class="token punctuation">.</span>products<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>product <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> product<span class="token punctuation">.</span>category <span class="token operator">===</span> filterCategory
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// getters.spec.js</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> expect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'chai'</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> getters <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./getters'</span>

<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'getters'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'filteredProducts'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 模拟状态</span>
    <span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span>
      products<span class="token punctuation">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Apple'</span><span class="token punctuation">,</span> category<span class="token punctuation">:</span> <span class="token string">'fruit'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Orange'</span><span class="token punctuation">,</span> category<span class="token punctuation">:</span> <span class="token string">'fruit'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Carrot'</span><span class="token punctuation">,</span> category<span class="token punctuation">:</span> <span class="token string">'vegetable'</span> <span class="token punctuation">}</span>
      <span class="token punctuation">]</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// 模拟 getter</span>
    <span class="token keyword">const</span> filterCategory <span class="token operator">=</span> <span class="token string">'fruit'</span>

    <span class="token comment">// 获取 getter 的结果</span>
    <span class="token keyword">const</span> result <span class="token operator">=</span> getters<span class="token punctuation">.</span><span class="token function">filteredProducts</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> <span class="token punctuation">{</span> filterCategory <span class="token punctuation">}</span><span class="token punctuation">)</span>

    <span class="token comment">// 断言结果</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span>deep<span class="token punctuation">.</span><span class="token function">equal</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
      <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Apple'</span><span class="token punctuation">,</span> category<span class="token punctuation">:</span> <span class="token string">'fruit'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> title<span class="token punctuation">:</span> <span class="token string">'Orange'</span><span class="token punctuation">,</span> category<span class="token punctuation">:</span> <span class="token string">'fruit'</span> <span class="token punctuation">}</span>
    <span class="token punctuation">]</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre>
</div>
<h3 id="执行测试"><a href="#执行测试" aria-hidden="true" class="header-anchor">执行测试</a></h3>
<p>如果你的 mutation 和 action 编写正确，经过合理地 mocking 处理之后这些测试应该不依赖任何浏览器 API，因此你可以直接用 webpack 打包这些测试文件然后在 Node 中执行。换种方式，你也可以用
	<code>mocha-loader</code> 或 Karma + <code>karma-webpack</code>在真实浏览器环境中进行测试。</p>
<h4 id="在-node-中执行测试"><a href="#在-node-中执行测试" aria-hidden="true" class="header-anchor">在 Node 中执行测试</a></h4>
<p>创建以下 webpack 配置（配置好 <a href="https://babeljs.io/docs/usage/babelrc/" target="_blank" rel="noopener noreferrer"><code>.babelrc</code><svg
		 xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"
		 class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a>）:</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// webpack.config.js</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  entry<span class="token punctuation">:</span> <span class="token string">'./test.js'</span><span class="token punctuation">,</span>
  output<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    path<span class="token punctuation">:</span> __dirname<span class="token punctuation">,</span>
    filename<span class="token punctuation">:</span> <span class="token string">'test-bundle.js'</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  module<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    loaders<span class="token punctuation">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span>
        test<span class="token punctuation">:</span> <span class="token regex">/\.js$/</span><span class="token punctuation">,</span>
        loader<span class="token punctuation">:</span> <span class="token string">'babel-loader'</span><span class="token punctuation">,</span>
        exclude<span class="token punctuation">:</span> <span class="token regex">/node_modules/</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">]</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<p>然后：</p>
<div class="language-bash extra-class">
	<pre class="language-bash"><code>webpack
mocha test-bundle.js
</code></pre>
</div>
<h4 id="在浏览器中测试"><a href="#在浏览器中测试" aria-hidden="true" class="header-anchor">在浏览器中测试</a></h4>
<ol>
	<li>安装 <code>mocha-loader</code>。</li>
	<li>把上述 webpack 配置中的 <code>entry</code> 改成 <code>'mocha-loader!babel-loader!./test.js'</code>。</li>
	<li>用以上配置启动 <code>webpack-dev-server</code>。</li>
	<li>访问 <code>localhost:8080/webpack-dev-server/test-bundle</code>。</li>
</ol>
<h4 id="使用-karma-karma-webpack-在浏览器中执行测试"><a href="#使用-karma-karma-webpack-在浏览器中执行测试" aria-hidden="true" class="header-anchor">使用 Karma + karma-webpack 在浏览器中执行测试</a></h4>
<p>详见 <a href="https://vuejs.github.io/vue-loader/workflow/testing.html" target="_blank" rel="noopener noreferrer">vue-loader
		documentation<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15"
		 height="15" class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a>。</p>
	
	
<br><br>
	
		
<h2 id="hot-reload">
	<a href="#hot-reload" class="headerlink" title="hot-reload" data-scroll="">热重载</a>
</h2>	
<p>使用 webpack 的 <a href="https://webpack.js.org/guides/hot-module-replacement/" target="_blank" rel="noopener noreferrer">Hot
		Module Replacement API<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100"
		 width="15" height="15" class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a>，Vuex 支持在开发过程中热重载 mutation、module、action 和 getter。你也可以在 Browserify 中使用 <a href="https://github.com/AgentME/browserify-hmr/"
	 target="_blank" rel="noopener noreferrer">browserify-hmr<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px"
		 y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a> 插件。</p>
<p>对于 mutation 和模块，你需要使用 <code>store.hotUpdate()</code> 方法：</p>
<div class="language-js extra-class">
	<pre class="language-js"><code><span class="token comment">// store.js</span>
<span class="token keyword">import</span> Vue <span class="token keyword">from</span> <span class="token string">'vue'</span>
<span class="token keyword">import</span> Vuex <span class="token keyword">from</span> <span class="token string">'vuex'</span>
<span class="token keyword">import</span> mutations <span class="token keyword">from</span> <span class="token string">'./mutations'</span>
<span class="token keyword">import</span> moduleA <span class="token keyword">from</span> <span class="token string">'./modules/a'</span>

Vue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Vuex<span class="token punctuation">)</span>

<span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>

<span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  state<span class="token punctuation">,</span>
  mutations<span class="token punctuation">,</span>
  modules<span class="token punctuation">:</span> <span class="token punctuation">{</span>
    a<span class="token punctuation">:</span> moduleA
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span>module<span class="token punctuation">.</span>hot<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 使 action 和 mutation 成为可热重载模块</span>
  module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'./mutations'</span><span class="token punctuation">,</span> <span class="token string">'./modules/a'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 获取更新后的模块</span>
    <span class="token comment">// 因为 babel 6 的模块编译格式问题，这里需要加上 `.default`</span>
    <span class="token keyword">const</span> newMutations <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./mutations'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">default</span>
    <span class="token keyword">const</span> newModuleA <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./modules/a'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">default</span>
    <span class="token comment">// 加载新模块</span>
    store<span class="token punctuation">.</span><span class="token function">hotUpdate</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      mutations<span class="token punctuation">:</span> newMutations<span class="token punctuation">,</span>
      modules<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        a<span class="token punctuation">:</span> newModuleA
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
</div>
<p>参考热重载示例 <a href="https://github.com/vuejs/vuex/tree/dev/examples/counter-hot" target="_blank" rel="noopener noreferrer">counter-hot<svg
		 xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"
		 class="icon outbound">
			<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
			<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
		</svg></a>。</p>
	
	
</div>
		<!-- important -->

<!-- var end -->
</div>	<!-- #main -->

<script>
	
var thisAction = '<?php echo ($thisAction); ?>';

if (thisAction == 'all') {
	// sidebar全部显示
	var $link = $('.content .headerlink');
	var $slink = $('.section-link');
	
}else {
	// 仅展开 当前actionName
	$('.menu-sub').hide();
	$('#'+thisAction+'>a').addClass('current'); 
	$('#'+thisAction+'>i').addClass('sidebar-tap').html('－');
	$('#'+thisAction+' .menu-sub').show();


	$('.sidebar-menu>i').click(function(){
		if($(this).hasClass('sidebar-tap')) {
			$(this).html('＋').toggleClass('sidebar-tap');
			$(this).siblings('.menu-sub').hide();
		}else {
			$('.sidebar-menu>i').html('＋').removeClass('sidebar-tap');
			$('.sidebar-menu .menu-sub').hide();

			$(this).html('－').toggleClass('sidebar-tap');
			$(this).siblings('.menu-sub').show();
		}
	});


	let href = window.location.href;
	let start = href.indexOf('#');
	let href2 = '';
	if(start > 0) {
		href2 = href.slice(start+1);
		$('#'+thisAction+' .section-link[href="#'+href2+'"]').addClass('active');
	}else {
		$('#'+thisAction+' .menu-sub .section-link:first').addClass('active');
	}
 
	var $link = $('.content .headerlink');
	var $slink = $('#'+thisAction+' .menu-sub .section-link');
	
	$('#'+thisAction+' .section-link').click(function(){
		$slink.removeClass('active');
		$(this).addClass('active');
	});
}



// 页面滚动 .sidebar提示 start
let scrollArr = [];
$.each( $link, function() {
	let offset = $(this).offset();
	let thisId = $(this).attr('id');
	scrollArr.push(offset.top);
});


$(window).on('scroll', function(){
	let scrollTop = $(document).scrollTop();
	let nap = 110;
	let slength = scrollArr.length;
	let i=0;
	if(scrollTop < (scrollArr[0]-nap) ) {
	}else if(scrollTop >= scrollArr[slength-1]-nap) {
		i = slength-1;
	}else {
		for(i=0; i<scrollArr.length; i++) {
			if(scrollTop>=scrollArr[i]-nap && scrollTop<scrollArr[i+1]-nap) {
				break;
			}
		}
	}

	if($slink.eq(i).length > 0){
		$slink.removeClass('active');
		$slink.eq(i).addClass('active');
	}
});


</script>

    
  </body>
</html>